import { InnerMenu } from './../../../../models/inner-menu';
import { Subscription } from 'rxjs';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Component, OnInit, ViewChild, AfterViewInit, ElementRef, ViewContainerRef, OnDestroy } from '@angular/core';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ExceptionHandler } from 'src/app/handler/exception.handler';
import { NodePermitModalComponent } from './node-permit-modal/node-permit-modal.component';
import { G6GraphTool } from './treeGraph';
import { EditRoleUserModalComponent } from './edit-role-user-modal/edit-role-user-modal.component';
import { PermitPerviewModalComponent } from './permit-perview-modal/permit-perview-modal.component';
import { AccountRoles, ZepridePageTemplate, Account } from 'src/app/models';
import { PermitItem } from 'src/app/models/permitItem';
import { OrganizationService } from 'src/app/services/organization.service';
import { PermitService } from 'src/app/services/permit.service';
import { RoleService } from 'src/app/services/role.service';
import { WorkflowNodeService } from '../../../../services/workflow-node.service';
import { MenuService } from 'src/app/services/menu.service';

@Component({
  selector: 'zepride-permission',
  templateUrl: './permission.component.html',
  styleUrls: ['./permission.component.less']
})
export class PermissionComponent implements OnInit, AfterViewInit, OnDestroy {
  @ViewChild('container') container: ElementRef<HTMLDivElement>;
  @ViewChild('minimapContainerRef') minimapContainer: ElementRef<HTMLDivElement>;
  departmentNodes = [];
  employeeNodes = [];
  departmentInfo;
  roles = [];
  permitList: PermitItem[] = [];
  nodeItemClickSubscription: Subscription;
  pageType: string;
  curMenu: InnerMenu;
  curSMenu: InnerMenu;
  menuList: InnerMenu[] = [];

  mode: 'department' | 'role' = 'department';
  canConfigRole = true;
  topSelectValue;
  configMode: 'independent' | 'role' = 'independent';
  selectRole;
  curAccountRoles: AccountRoles[] = [];
  curPageDataChangedArgs;

  constructor(
    private modal: NzModalService,
    private viewContainerRef: ViewContainerRef,
    private orgSvr: OrganizationService,
    private permitSvr: PermitService,
    private flowNodeSvr: WorkflowNodeService,
    private msg: NzMessageService,
    private roleSvr: RoleService,
    private menuSvr: MenuService
  ) { }
  ngOnDestroy(): void {
    if (this.nodeItemClickSubscription) {
      this.nodeItemClickSubscription.unsubscribe();
    }
    G6GraphTool.current.destroy();
  }

  ngAfterViewInit(): void {
    this.nodeItemClickSubscription = G6GraphTool.current.nodeItemClick$.subscribe((data) => {
      if (this.pageType == 'normalPage') {
        this.nodeClick(data);
      }
      else if (this.pageType == 'workflow') {
        this.workflowNodeClick(data);
      }
      // else if (this.pageType == 'admin') {
      //   // 超级权限
      //   this.adminNodeClick();
      // }
    });
  }

  async ngOnInit() {
    await this.getDepartmentNodes();
    await this.getMenuList();
  }

  async getMenuList() {
    const result = await this.menuSvr.queryMenus();
    this.menuList = result.list;
  }

  async getDepartmentNodes() {
    try {
      const orgTreeNode = await this.orgSvr.getOrganizationTrees({ objectId: this.orgSvr.orgid });
      this.departmentNodes = await this.orgSvr.getOrganizationTrees({
        parentId: orgTreeNode[0].id,
        objectName: 'Department'
      });
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  async departmentChanged(department) {
    this.departmentInfo = department;
    await this.getEmployees(department.id);
    await this.getObjectPermits({ id: department.objectId });
  }

  private async getEmployees(departmentNodeId: string) {
    try {
      this.employeeNodes = await this.orgSvr.getOrganizationTrees({
        parentId: departmentNodeId,
        objectName: 'User'
      });

      // this.employeeNodes.unshift(this.departmentInfo);
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  async modeChanged(item) {
    this.mode = item;
    this.configMode = 'independent';

    if (this.mode == 'department') {
      await this.getObjectPermits({ id: this.departmentInfo.objectId });
    }
    else if (this.mode == 'role') {
      await this.getObjectPermits(this.selectRole);
    }
  }

  async topBarValueChanged(item) {
    G6GraphTool.current.clean();
    this.curPageDataChangedArgs = null;
    this.permitList = [];
    if (item.objectName == 'Department') {
      this.canConfigRole = false;
      this.configMode = 'independent';
    }
    else {
      this.canConfigRole = true;
    }

    try {
      this.topSelectValue = await this.orgSvr.getOrganizationTreeInfoById(item.id);

      if (this.topSelectValue.objectName == 'User') {
        await this.chooseRoles();
        const p = await this.permitSvr.getUserPermits(this.topSelectValue.object.id, this.topSelectValue.object.accountId);
        this.permitList = this.permitList.concat(p);
      }
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  private async chooseRoles() {
    const acList = await this.roleSvr.getUserRoles({ accountId: this.topSelectValue.object.accountId });
    this.roles.forEach(x => {
      if (acList.find(n => n.roleId == x.id)) {
        x.checked = true;
      }
      else {
        x.checked = false;
      }
    });
  }

  roleValueChanged(roles) {
    this.roles = roles;
  }

  async roleSelectChanged(role: { id: string; }) {
    if (!role) {
      return;
    }
    this.selectRole = role;
    await this.getObjectPermits(role);
    await this.getRoleUsers(role.id);
  }

  private async getObjectPermits(object: any) {
    if (!object) {
      return;
    }
    this.permitList = [];
    try {
      const p = await this.permitSvr.queryAccountPermits({
        authObjectId: object.id
      });
      this.permitList = this.permitList.concat(p);
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  private getNodeColor(x: ZepridePageTemplate) {
    const yellow = '#FF9500';
    const green = '#45C650';
    let color = '#C0C4CC';
    const isGreen = x.template.tmpComItems.filter(n => n.component.perimitConfig && n.component.perimitConfig.length).every(n => n.permitAllChecked);
    if (isGreen) {
      color = green;
    }
    else {
      const isYellow = x.template.tmpComItems.some(n => n.component.perimitConfig.some(m => m.permitSelected));
      if (isYellow) {
        color = yellow;
      }
    }

    return color;
  }

  async onPageDataChanged(args: { pageData: any; menu: any; smenu: any }) {
    this.curPageDataChangedArgs = args;
    this.pageType = args.pageData.type;
    this.curMenu = args.menu;
    this.curSMenu = args.smenu;

    if (args.pageData.type == 'normalPage') {
      this.setSelectPermits(args.pageData.pageTmpItems);
      const d = {
        nodes: []
      };
      d.nodes = [].concat(args.pageData.pageTmpItems.map((x: ZepridePageTemplate) => {
        const color = this.getNodeColor(x);
        const menuHasPermit = color != '#C0C4CC';
        if (menuHasPermit) {
          this.setMenuPermit();

        }

        return {
          id: x.templateId,
          label: x.template.name,
          data: x,
          color
        };
      }));

      G6GraphTool.current.renderNodeGraph(this.container, d, 'LR', this.minimapContainer);
    }
    else if (args.pageData.type == 'workflow') {
      const d = {
        nodes: [],
        edges: []
      };

      this.clearMenuAndPagePermit();

      let menuHasPermit = false;
      for (const x of args.pageData.workflowNodeItems) {
        let color = '#C0C4CC';
        const flowNode = await this.getFlowNodeInfo(x.flowNodeId);

        if (flowNode.pages && flowNode.pages.length) {
          this.setSelectPermits(flowNode.pages[0].pageTmpItems);

          if (flowNode.pages[0].pageTmpItems.every(pageTmpItem => pageTmpItem.template.tmpComItems.every(tmpComItem => tmpComItem.permitAllChecked))) {
            color = '#45C650';
            menuHasPermit = true;
          }
          else {
            if (flowNode.pages[0].pageTmpItems.some(pageTmpItem => pageTmpItem.template.tmpComItems.some(tmpComItem => tmpComItem.component.perimitConfig.length && tmpComItem.component.perimitConfig.some(pItem => pItem.permitSelected)))) {
              color = '#FF9500';
              menuHasPermit = true;
            }
          }
        }

        x.color = color;
      }

      if (menuHasPermit) {
        this.setMenuPermit();
      }

      d.nodes = args.pageData.workflowNodeItems.map(x => {
        return {
          id: x.flowNodeId,
          label: x.flowNode.name,
          color: x.color
        };
      });

      d.edges = args.pageData.paths.map(x => {
        return {
          source: x.headNodeId,
          target: x.endNodeId
        };
      });

      G6GraphTool.current.renderNodeGraph(this.container, d, 'TB', this.minimapContainer);
    }
  }

  private async workflowNodeClick(item) {
    try {
      const flowNode = await this.flowNodeSvr.getFlowNodeById(item.id);
      if (flowNode.pages.length == 0) {
        this.msg.error('当前节点未配置页面！');
        return;
      }
      const pageTmpItems = flowNode.pages[0].pageTmpItems;
      this.setSelectPermits(pageTmpItems);
      const modal = this.modal.create({
        nzTitle: `【${item.label}】组件权限配置`,
        nzContent: NodePermitModalComponent,
        nzViewContainerRef: this.viewContainerRef,
        nzWidth: 800,
        nzComponentParams: {
          data: pageTmpItems,
          permits: this.permitList
        },
        nzFooter: null
      });

      modal.afterClose.subscribe((permitList: ZepridePageTemplate[]) => {
        if (permitList) {
          this.getAccountPermits(permitList);
          this.onPageDataChanged(this.curPageDataChangedArgs);
          // console.log('xxxxxxxx', this.permitList);
        }
      });

    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  private nodeClick(item) {
    const modal = this.modal.create({
      nzTitle: `【${item.label}】组件权限配置`,
      nzContent: NodePermitModalComponent,
      nzViewContainerRef: this.viewContainerRef,
      nzWidth: 800,
      nzComponentParams: {
        data: [item.data],
        permits: this.permitList
      },
      nzFooter: null
    });

    modal.afterClose.subscribe((permitList: ZepridePageTemplate[]) => {
      if (permitList) {
        this.getAccountPermits(permitList);
        this.onPageDataChanged(this.curPageDataChangedArgs);
      }

    });
  }

  getAuthObject() {
    const authObject = {
      authObjectId: '',
      authObjectType: ''
    };
    if (this.mode == 'department') {
      authObject.authObjectId = this.departmentInfo.objectId;
      authObject.authObjectType = this.departmentInfo.objectName;
    }
    else if (this.mode == 'role') {

      authObject.authObjectId = this.selectRole.id;
      authObject.authObjectType = 'Role';
    }

    return authObject;
  }

  async savePermit() {
    if (this.configMode == 'independent') {
      const authObject = this.getAuthObject();
      if (this.mode == 'department') {
        // 授权给登录人员,  授权给部门
        this.permitList.forEach(item => {
          item.authObjectId = this.departmentInfo.objectId,
            item.authObjectType = this.departmentInfo.objectName;
        });
      }
      else if (this.mode == 'role') {
        // 授权给角色
        if (!this.selectRole) {
          this.msg.error('未选择角色信息！');
          return;
        }
        this.permitList.forEach(item => {
          item.authObjectId = this.selectRole.id,
            item.authObjectType = 'Role';
        });
      }


      try {
        await this.permitSvr.savePermists(this.permitList, authObject);
        this.msg.success('保存成功！');
        if (this.curPageDataChangedArgs) {
          this.onPageDataChanged(this.curPageDataChangedArgs);
        }

      } catch (error) {
        ExceptionHandler.current.handleError(error);
      }
    }
    // else {
    //   // 保存人员到角色
    //   // let req = [];
    //   // this.roles.filter(x => x.checked).forEach(item => {
    //   //   req.push({
    //   //     accountId: this.topSelectValue.object.accountId,
    //   //     roleId: item.id,
    //   //   })
    //   // })

    //   // await this.roleSvr.createAccountRoles(req);
    //   // this.msg.success('保存成功！');
    // }

  }

  private generMenuPermitItem(item) {
    const p: PermitItem = {
      permitId: `query#${item.id}`,
      permitName: `${item.name}`,
      refObjectId: item.id,
      refObjectType: 'Menu'
    };

    return p;
  }

  private addToPermits(item: PermitItem) {
    const has = this.permitList.some(x => x.refObjectId == item.refObjectId);
    if (!has) {
      this.permitList.push(item);
    }
  }

  private clearMenuAndPagePermit() {
    // 去掉当前的 page menu 权限，重新判断是否具有page menu 的权限
    this.permitList = this.permitList.filter(x => {
      if (x.refObjectId == this.curMenu.id) {
        return false;
      }
      if (x.refObjectId == this.curMenu.pageId) {
        return false;
      }

      return true;
    });
  }

  private setMenuPermit() {
    if (this.curMenu) {
      const menuPermitItem = this.generMenuPermitItem(this.curMenu);
      this.addToPermits(menuPermitItem);
    }

    if (this.curSMenu) {
      const smenuPermitItem = this.generMenuPermitItem(this.curSMenu);
      this.addToPermits(smenuPermitItem);
    }
  }

  getAccountPermits(data: ZepridePageTemplate[]) {
    data.forEach(pageTmpItem => {
      // if (pageTmpItem.template.tmpComItems.some(tmpComItem => tmpComItem.component.perimitConfig.some(x => x.permitSelected))) {
      //   // 有一个权限被选中则选中当前菜单
      //   console.log(this.curSMenu);
      //   const menuPermitItem = this.generMenuPermitItem(this.curMenu);
      //   // 添加页面权限（节点页面权限）
      //   const p: PermitItem = {
      //     permitId: `query#${pageTmpItem.pageId}`,
      //     permitName: `${pageTmpItem.name}`,
      //     refObjectId: pageTmpItem.pageId,
      //     refObjectType: 'Page'
      //   };

      //   this.addToPermits(p);

      //   // 添加父级菜单
      //   // if (this.curMenu.parentId) {
      //   //   const parentMenu = this.menuList.find(x => x.id == this.curMenu.parentId);
      //   //   if (parentMenu) {
      //   //     const parentMenuPermitItem = this.generMenuPermitItem(parentMenu);
      //   //     this.addToPermits(parentMenuPermitItem);
      //   //   }
      //   // }

      //   this.addToPermits(menuPermitItem);

      //   if(this.curSMenu){
      //     const smenuPermitItem = this.generMenuPermitItem(this.curSMenu);
      //     this.addToPermits(smenuPermitItem);
      //   }
      // }

      pageTmpItem.template.tmpComItems.forEach(tmpComItem => {
        tmpComItem.component.perimitConfig.forEach(pItem => {
          const permitItem = this.permitList.find(x => x.refObjectId == pItem.refObjectId && x.permitId == pItem.permitId);
          if (pItem.permitSelected) {
            if (!permitItem) {
              this.permitList.push(pItem as any);
            }
          }
          else {
            if (permitItem) { (<any>permitItem).del = true; }
          }
        });
      });

    });

    // console.log('xxxxxxxx', this.permitList.filter(x => (<any>x).del));

    this.permitList = this.permitList.filter(x => !( x as any).del);

    console.log('rrrrrrr', this.permitList);
  }



  setSelectPermits(data: ZepridePageTemplate[]) {
    data.forEach(pageTmpItem => {
      pageTmpItem.template.tmpComItems.forEach(tmpComItem => {
        tmpComItem.component.perimitConfig.forEach(pItem => {
          pItem.permitSelected = this.permitList.some(x => x.refObjectId == tmpComItem.id && x.permitId == pItem.permitId);
        });

        tmpComItem.permitAllChecked = tmpComItem.component.perimitConfig.length && tmpComItem.component.perimitConfig.every(x => x.permitSelected);
      });
    });
  }

  async getFlowNodeInfo(flowNodeId: string) {
    const node = await this.flowNodeSvr.getFlowNodeById(flowNodeId);
    return node;
  }

  async removeUserFromRole(item: AccountRoles) {
    try {
      await this.roleSvr.delAccountRolesById(item.id);
      this.getRoleUsers(this.selectRole.id);
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  async getRoleUsers(roleId: string) {
    this.curAccountRoles = await this.roleSvr.getUserRoles({ roleId });
  }

  checkAllocatedPermits() {
    const modal = this.modal.create({
      nzTitle: '检索机构未分配权限',
      nzContent: PermitPerviewModalComponent,
      nzViewContainerRef: this.viewContainerRef,
      nzWidth: 1000,
      nzComponentParams: {

      },
      nzFooter: null
    });
  }

  permitPerview() {
    const authObject = this.getAuthObject();
    const modal = this.modal.create({
      nzTitle: '所属权限快照',
      nzContent: PermitPerviewModalComponent,
      nzViewContainerRef: this.viewContainerRef,
      nzWidth: 1000,
      nzComponentParams: {
        mode: 'preview',
        authObjectId: authObject.authObjectId
      },
      nzFooter: null
    });

  }

  editRoleUser() {
    const modal = this.modal.create({
      nzTitle: `匹配角色`,
      nzContent: EditRoleUserModalComponent,
      nzViewContainerRef: this.viewContainerRef,
      nzWidth: 800,
      nzComponentParams: {
        departmentNodes: this.departmentNodes,
        roleId: this.selectRole.id
      },
      nzFooter: null
    });

    modal.afterClose.subscribe(result => {
      if (result == 'ok') {
        this.getRoleUsers(this.selectRole.id);
      }
    });
  }
}
